package com.wjh.www.service.impl;

import com.wjh.www.annotation.Transaction;
import com.wjh.www.annotation.spring.Autowired;
import com.wjh.www.annotation.spring.Component;
import com.wjh.www.dao.mapper.CourseMapper;
import com.wjh.www.dao.mapper.StudentCourseMapper;
import com.wjh.www.dao.mapper.UserMapper;
import com.wjh.www.entity.bo.StudentCourseBo;
import com.wjh.www.entity.dto.CommonResult;
import com.wjh.www.entity.po.Course;
import com.wjh.www.entity.po.StudentCourse;
import com.wjh.www.entity.po.User;
import com.wjh.www.entity.vo.ExcelVo;
import com.wjh.www.service.CourseService;
import com.wjh.www.service.constant.SystemConstant;
import com.wjh.www.util.ExcelUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 课程相关业务
 *
 * @author wjh
 * @date 2021/9/10 14:09
 * @Package com.wjh.anyview.service.impl
 */
@Component
public class CourseServiceImpl implements CourseService {
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private StudentCourseMapper studentCourseMapper;
    /**
     * 锁对象
     */
    private final ReentrantLock myLock = new ReentrantLock();

    @Override
    public CommonResult<?> addCourse(Course course) {
        //判断是否发布过课程
        if (courseMapper.selectOneByFields(course) != null) {
            return CommonResult.operateFailWithMessage("该课程已经发布过了！");
        }

        if (courseMapper.insert(course) > 0) {
            return CommonResult.operateSuccess();
        }
        return CommonResult.operateFailWithMessage(SystemConstant.SYSTEM_ERROR);

    }

    @Override
    public CommonResult<?> updateCourseById(Course course) {
        if (course.getId() == null) {
            return CommonResult.operateFailWithMessage("课程id不能为空");
        }
        if (course.getCurrentNum() != null) {
            return CommonResult.operateFailWithMessage("不可以修改已选学生数");
        }
        if (courseMapper.updateById(course) > 0) {
            return CommonResult.operateSuccess();
        }
        return CommonResult.operateFailWithMessage(SystemConstant.SYSTEM_ERROR);
    }

    @Override
    public CommonResult<?> deleteCourseById(Long courseId) {
        Course courseDelete = new Course();
        courseDelete.setId(courseId);
        if (courseMapper.delete(courseDelete) > 0) {
            return CommonResult.operateSuccess();
        }
        return CommonResult.operateFailWithMessage(SystemConstant.SYSTEM_ERROR);
    }

    @Override
    public CommonResult<List<Course>> queryCourseByGrade(Integer grade) {
        Course courseSelect = new Course();
        courseSelect.setGrade(grade);
        List<Course> courseList = courseMapper.selectListByFields(courseSelect);
        if (courseList.size() > 0) {
            return CommonResult.operateSuccess(courseList);
        }
        return CommonResult.operateFailWithMessage(SystemConstant.SYSTEM_ERROR);
    }

    @Override
    public CommonResult<?> choiceCourse(StudentCourseBo studentCourseBo) {
        Long studentId = studentCourseBo.getStudentId();
        Long courseId = studentCourseBo.getCourseId();

        User user = userMapper.selectById(new User(studentId));
        Course course = courseMapper.selectById(new Course(courseId));
        //该学生不能选择其它年级的课程
        if (!user.getGrade().equals(course.getGrade())) {
            return CommonResult.operateFailWithMessage("您不能选择其它年级的课程！");
        }
        //选课时间未到
        if (new Timestamp(course.getStartTime().getTime()).after(new Timestamp(System.currentTimeMillis()))) {
            return CommonResult.operateFailWithMessage("该课程还没有到选课时间！");
        }
        //查询该学生的预选课程，判断选课是否有冲突
        List<Course> preCourseList = queryPreCourseByStudentId(studentId).getData();
        if (preCourseList != null) {
            for (Course preCourse : preCourseList) {
                Course courseSelect = new Course();
                //根据星期几和第几节课来判断是否有课程冲突
                courseSelect.setWeekDay(preCourse.getWeekDay());
                courseSelect.setBatch(preCourse.getBatch());
                if (courseMapper.selectOneByFields(courseSelect) != null) {
                    return CommonResult.operateFailWithMessage("该课程和您之前所选课程上课时间上有冲突！");
                }
            }
        }
        //开启抢课业务
        myLock.lock();
        try {
            //课程人数可能会发生变化，需要再查一次
            Course courseCurrent = courseMapper.selectById(new Course(courseId));
            //课程已经被抢光了
            if (courseCurrent.getCurrentNum() >= courseCurrent.getMaxNum()) {
                return CommonResult.operateFailWithMessage("你来完了，该课程已经被洗劫一空！");
            }

            //student_course表中的status字段默认是0，即默认未预选状态
            StudentCourse studentCourse = new StudentCourse();
            studentCourse.setStudentId(studentId);
            studentCourse.setCourseId(courseId);
            if (studentCourseMapper.selectOneByFields(studentCourse) != null) {
                return CommonResult.operateFailWithMessage("您已经预选或已确选了该课程了，不能再次选择！");
            }
            //选课成功
            int result = studentCourseMapper.insert(studentCourse);
            if (result <= 0) {
                return CommonResult.operateFailWithMessage(SystemConstant.SYSTEM_ERROR);
            }
            Course courseUpdate = new Course();
            //已选课程数量加1
            courseUpdate.setCurrentNum(courseCurrent.getCurrentNum() + 1);
            //版本号加1
            courseUpdate.setVersion(courseCurrent.getVersion() + 1);
            Map<String, Object> map = new HashMap<>(2);
            map.put("id", courseId);
            map.put("version", courseCurrent.getVersion());

            //更新数据中的信息
            if (courseMapper.updateByMap(courseUpdate, map) > 0) {
                return CommonResult.operateFailWithMessage("预选该课程成功！");
            }
        } finally {
            myLock.unlock();
        }
        return CommonResult.operateFailWithMessage(SystemConstant.SYSTEM_ERROR);
    }

    @Override
    public CommonResult<List<Course>> queryPreCourseByStudentId(Long studentId) {
        StudentCourse studentCourseSelect = new StudentCourse();
        studentCourseSelect.setStudentId(studentId);
        //只查询预选课程
        studentCourseSelect.setStatus(0);
        //更加学生id查询学生对象
        List<StudentCourse> studentCourses = studentCourseMapper.selectListByFields(studentCourseSelect);

        List<Course> list = new ArrayList<>();
        //根据课程id查询课程对象
        studentCourses.forEach(studentCourse -> {
            Course course = courseMapper.selectById(new Course(studentCourse.getCourseId()));
            list.add(course);
        });

        if (list.size() > 0) {
            return CommonResult.operateSuccess(list);
        }
        return CommonResult.operateFailWithMessage(SystemConstant.SYSTEM_ERROR);
    }

    @Override
    public CommonResult<?> affirmCourse(StudentCourseBo studentCourseBo) {
        StudentCourse studentCourse = new StudentCourse();
        //1表示确认选择该门课程
        studentCourse.setStatus(1);
        Map<String, Object> map = new HashMap<>(2);
        map.put("courseId", studentCourseBo.getCourseId());
        map.put("studentId", studentCourseBo.getStudentId());
        //更新数据库
        if (studentCourseMapper.updateByMap(studentCourse, map) > 0) {
            return CommonResult.operateSuccess();
        }
        return CommonResult.operateFailWithMessage(SystemConstant.SYSTEM_ERROR);
    }

    @Override
    @Transaction
    public CommonResult<?> cancelCourse(StudentCourseBo studentCourseBo) {
        Long studentId = studentCourseBo.getStudentId();
        Long courseId = studentCourseBo.getCourseId();

        StudentCourse studentCourse = new StudentCourse();
        studentCourse.setStudentId(studentId);
        studentCourse.setCourseId(courseId);
        studentCourse.setStatus(0);

        myLock.lock();
        try {
            studentCourseMapper.delete(studentCourse);
            Course courseCurrent = courseMapper.selectById(new Course(courseId));
            Course courseUpdate = new Course();
            //已选人数减去1
            courseUpdate.setCurrentNum(courseCurrent.getCurrentNum() - 1);
            //版本号加1
            courseUpdate.setVersion(courseCurrent.getVersion() + 1);
            Map<String, Object> map = new HashMap<>(2);
            map.put("version", courseCurrent.getVersion());
            map.put("id", courseId);

            if (courseMapper.updateByMap(courseUpdate, map) > 0) {
                return CommonResult.operateSuccess();
            }
        } finally {
            myLock.unlock();
        }
        return CommonResult.operateFailWithMessage(SystemConstant.SYSTEM_ERROR);
    }

    @Override
    public CommonResult<ExcelVo> listCourseInExcel(Long studentId) {
        StudentCourse studentCourseSelect = new StudentCourse();
        studentCourseSelect.setStudentId(studentId);
        //只查询学习已经确认的课程
        studentCourseSelect.setStatus(1);
        //更加学生id查询学生对象
        List<StudentCourse> studentCourses = studentCourseMapper.selectListByFields(studentCourseSelect);

        List<Course> list = new ArrayList<>();
        //根据课程id查询课程对象
        studentCourses.forEach(studentCourse -> {
            Course course = courseMapper.selectById(new Course(studentCourse.getCourseId()));
            list.add(course);
        });

        if (list.size() > 0) {
            //excel表格的列标题
            String[] title = {"课程名", "地点", "上课时间", "节次", "课程最大人数", "当前人数", "课程描述", "年级"};
            //定义excel表格的文件名
            String fileName = "我的课表.xls";
            //脚本名
            String sheetName = "我的课表";
            //没有数据传入null吧，Excel工具类会对null进行判断
            String[][] content = new String[list.size()][8];

            for (int i = 0; i < list.size(); i++) {
                content[i] = new String[title.length];
                Course course = list.get(i);
                content[i][0] = course.getName();
                content[i][1] = course.getLocation();
                content[i][2] = "星期" + course.getWeekDay();
                content[i][3] = "第" + course.getBatch() + "节";
                content[i][4] = course.getMaxNum() + "人";
                content[i][5] = course.getCurrentNum() + "人";
                content[i][6] = course.getDescription();
                content[i][7] = "大" + course.getGrade();
            }

            //创建HSSFWorkbook(excel表格)
            HSSFWorkbook wb = ExcelUtil.getHssfWorkbook(sheetName, title, content, null);
            ExcelVo excelVo = new ExcelVo();
            excelVo.setFileName(fileName);
            excelVo.setWb(wb);
            return CommonResult.operateSuccessWithFile(excelVo);
        }
        return CommonResult.operateFailWithMessage(SystemConstant.SYSTEM_ERROR);
    }

    @Override
    public CommonResult<List<Course>> queryAllCourse() {
        List<Course> list = courseMapper.selectListByFields(new Course());
        return CommonResult.operateSuccess(list);
    }
}
